import mediapipe as mp
import cv2
import numpy as np

class Hands:
    def __init__(self):
        self.mp_hands = mp.solutions.hands.Hands()
        self.frame = None
        self.landmark = []

    def draw_style(self, frame):
        # 无需再次实例化Hands对象，直接使用self.mp_hands
        result = self.mp_hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
        hand_landmarks_list = result.multi_hand_landmarks
        hand_colors = [(0, 255, 0), (255, 0, 0)]
        if not hand_landmarks_list:
            return frame

        for landmarks,color in zip(hand_landmarks_list,hand_colors):
            self.landmark = [lm for lm in landmarks.landmarkl]
            conns = mp.solutions.hands_connections.HAND_CONNECTIONS
            hands_style = mp.solutions.drawing_utils.DrawingSpec(color=(0, 25, 0), thickness=2)
            conns_style = mp.solutions.drawing_utils.DrawingSpec(color=(100, 0, 0), thickness=2)
            mp.solutions.drawing_utils.draw_landmarks(
                image=frame,
                landmark_list=landmarks,
                connections=conns,
                landmark_drawing_spec=hands_style,
                connection_drawing_spec=conns_style,
            )

            for index, lm in enumerate(self.landmark):
                x, y = int(lm.x * frame.shape[1]), int(lm.y * frame.shape[0])
                cv2.putText(frame, str(index), (x, y),
                            fontFace=cv2.FONT_ITALIC,
                            fontScale=0.6,
                            color=(0, 0, 0),
                            thickness=1)
            if result.multi_handedness:
                for hand in result.multi_handedness:
                    if hand.classification[0].label == "Left":
                        print("左手")
                    else:
                        print("右手")
        return frame

    def gesture_num(self, frame):
        top_point_num = [4, 8, 12, 16, 20]
        finger_status = np.zeros((6,), dtype=np.int8)
        for index, num in enumerate(top_point_num):
            if index == 0:
                continue
            top_p = self.index_convert_num(num)[1]
            mid_p = self.index_convert_num(num - 2)[1]
            finger_status[index] = top_p < mid_p
        top_p1 = self.index_convert_num(4)[0]
        mid_p1 = self.index_convert_num(2)[0]
        finger_status[index+1] = top_p1 < mid_p1

        cnt = np.sum(finger_status)
        print(cnt)

        cv2.putText(frame, str(cnt), (20, 50),
                    cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=0.5,
                    color=(54, 87, 48),
                    thickness=1)

    def index_convert_num(self, index):
        lm = self.landmark[index]
        x, y = int(lm.x * self.frame.shape[1]), int(lm.y * self.frame.shape[0])
        return x, y

    def process(self, frame):
        self.frame = frame
        frame = self.draw_style(frame)
        self.gesture_num(frame)
        return frame

if __name__ == '__main__':
    hands = Hands()
    cap = cv2.VideoCapture(0)
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        frame = hands.process(frame)
        cv2.imshow('hands', frame)
        if cv2.waitKey(60) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()